#include "python_caller.h"

PythonCaller* PythonCaller::m_instance = nullptr;

PythonCaller::PythonCaller()
{
    std::cout << "set python home" << std::endl;
    wchar_t* wide_python_home = Py_DecodeLocale("/home/marvsmart/miniconda3/envs/sg", nullptr);
    Py_SetPythonHome(wide_python_home);


    // // 手动设置 Python 的标准库路径
    // wchar_t* wide_python_path = Py_DecodeLocale("/home/username/anaconda3/envs/sg/lib/python3.10", nullptr);

    // if (wide_python_path == nullptr) {
    //     std::cerr << "Failed to decode Python path!" << std::endl;
    //     PyMem_RawFree(wide_python_home);
    //     return nullptr;
    // }

    // std::cout << "set python path" << std::endl;
    // Py_SetPath(wide_python_path);

    // 初始化Python解释器
    std::cout << "python initialize" << std::endl;
    Py_Initialize();
    std::cout << "python import onnx" << std::endl;
    PyRun_SimpleString("import onnx");
    std::cout << "python import onnxruntime" << std::endl;
    PyRun_SimpleString("import onnxruntime");
    std::cout << "python import transforms" << std::endl;
    PyRun_SimpleString("from torchvision import transforms");
    std::cout << "python import torch" << std::endl;
    PyRun_SimpleString("import torch");
    std::cout << "python import cv2" << std::endl;
    PyRun_SimpleString("import cv2");
    std::cout << "python import numpy" << std::endl;
    PyRun_SimpleString("import numpy");

    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('/home/marvsmart/workspace/shoe_keypoint_infer')");

    // 导入Python模块
    m_pModule = PyImport_ImportModule("onnx_infer");
    if (m_pModule == nullptr) {
        PyErr_Print();
        std::cerr << "Failed to import Python module" << std::endl;
        return;
    }

    // 获取Python函数
    m_pProcessImageFunc = PyObject_GetAttrString(m_pModule, "process_image");
    if (m_pProcessImageFunc == nullptr || !PyCallable_Check(m_pProcessImageFunc)) {
        PyErr_Print();
        std::cerr << "Failed to get Python function" << std::endl;
        return;
    }

    _import_array();  // 必须调用这个函数来初始化NumPy API
}


PythonCaller* PythonCaller::getInstance()
{
    if(m_instance == nullptr)
        m_instance = new PythonCaller();

    return m_instance;
}


void* PythonCaller::ProcessImage(cv::Mat &image, double* result) {

    // 将OpenCV的Mat对象转换为Python的numpy数组
    
    npy_intp dims[3] = {image.rows, image.cols, image.channels()};
    std::cout << "npy_intp " << image.rows << ", " << image.cols << ", " << image.channels() << std::endl;
    PyObject *py_array = PyArray_SimpleNewFromData(3, dims, NPY_UINT8, image.data);

    // 调用Python函数
    PyObject *pArgs = PyTuple_New(1);
    PyTuple_SetItem(pArgs, 0, py_array);
    PyObject *pResult = PyObject_CallObject(m_pProcessImageFunc, pArgs);

    if (pResult == nullptr)
    {
        std::cout << "pResult is null" << std::endl;
    }
    else if (PyList_Check(pResult))
    {
        for (int i = 0; i < PyList_Size(pResult); ++i) 
        {
            PyObject *pValue = PyList_GetItem(pResult, i);
            if (PyFloat_Check(pValue)) 
            {
                double rvalue = PyFloat_AsDouble(pValue);
                result[i] = rvalue;
            }
            else
            {
                std::cout << "pValue check failed" << std::endl;
            }
        }
    } else {
        PyErr_Print();
        std::cerr << "Failed to get result from Python function" << std::endl;
    }

    // 清理Python对象
    Py_XDECREF(pResult);
    Py_XDECREF(pArgs);
    Py_XDECREF(m_pProcessImageFunc);
    Py_XDECREF(m_pModule);

    // 关闭Python解释器
    Py_Finalize();

    return NULL;
}
